# -*- coding: utf-8 -*-

import urllib2

from kivy.logger import Logger
from kivy.uix.boxlayout import BoxLayout
from kivy.properties import NumericProperty
from kivy.clock import Clock

from model import gamestate
from model.gamestate import Players, Word, Hat
from ui.hat_widget import HatWidget, open_ok_popup
from constants import HOST
from model.json_loader import JsonLoader


class PlayerNameLayout(BoxLayout):
    """ Class for labels with players' names
    """

    def __init__(self, root, index, name, **kwargs):
        self.root = root
        self.index = index
        self.name = name
        super(PlayerNameLayout, self).__init__(**kwargs)

    def delete_player(self, index):
        for word in self.root.game_state.hat.words:
            if word.owner is not None:
                if word.owner.name == self.name:
                    del word
        del (self.root.game_state.players.players[index])
        self.root.update()


class StartGame(HatWidget):
    """ Class for Start Game screen

        Start Game screen lists all connected players. The user can add
        player and start the game, when number of players is even.

        Does not change the gamestate
        Needs:
            gamestate has players attribute,
            gamestate.remote_id MUST be None,
            list of players either exists or is None
        Does:
            Shows list of connected players
        Buttons:
            'Add Player' -> Add Player screen
            'Start!' -> Players Order screen
    """

    def __init__(self, game_state, presenter, **kwargs):
        """ Sets up the screen and saves game state and main presenter

            Args:
                game_state: (GameState) current state of the game
                presenter: (Presenter)  master presenter
                **kwargs: ()            misc arguments for widget creation
            Returns:
                None
        """
        self.game_state = game_state
        super(StartGame, self).__init__(presenter, **kwargs)

        if game_state.players is None:
            game_state.players = Players([])
        if game_state.hat is None:
            game_state.hat = Hat([])
        if self.game_state.current_added_player is not None\
           and self.game_state.current_added_player.finished_entering:
            if self.game_state.remote_id is not None:
                self.send_player(self.game_state.current_added_player)
            else:
                self.game_state.players.add(self.game_state.
                                            current_added_player)
            self.game_state.current_added_player = None
        self.players_list.height = (len(game_state.players.players) *
                                    self.height * 0.6)
        Clock.schedule_once(self.update, 0.05)

        if not self.game_state.is_game_host:
            self.join_btn.text = _('Host game')
            self.update_id_label()
        else:
            self.join_btn.text = _('Update')

    def update(self, *args):
        """ Updates the list of players when it changes
        """
        if self.game_state.remote_id is not None:
            self.update_id_label()
            self.load_players()
        self.players_list.clear_widgets()
        players = self.game_state.players.players
        index = 0
        for player in players:
            self.players_list.add_widget(PlayerNameLayout(self, index,
                                                          player.name))
            index += 1
        self.start_btn.enabled = not(len(players) < 2 and
                                     self.game_state.remote_id is None)
        self.count = len(players)

    def start_btn_released(self):
        """ Handles the event when start button is released
        """
        self.start_game()

    def start_game(self):
        """ Go to the next screen which displays the players order
        """
        if len(self.game_state.players.players) < 2:
            open_ok_popup(_('Not enough players'),
                          _('At least two players needed'), self)
            return
        if self.game_state.remote_id is not None:
            self.load_players()
        for player in self.game_state.players.players:
            for word in player.words:
                self.game_state.hat.add_word(word)
        self.presenter.change_phase(gamestate.Phase.PLAYERS_ORDER)

    def go_back(self):
        """ Go to the previous screen """
        self.presenter.change_phase(gamestate.Phase.GAME_CONFIG)

    def add_player(self):
        """ Go to the next screen which displays the Add Player screen
        """
        self.presenter.change_phase(gamestate.Phase.ADD_PLAYER)

    def join_to_game(self):

        if self.join_btn.text != _('Update'):
            try:
                self.game_state.is_game_host = True
                loader = JsonLoader()
                data = loader.load_from_url(
                    HOST+'/create_empty_game?words_number='+str(
                        self.game_state.settings.words_number))
                print data
                self.game_state.remote_id = data[u'id']
                self.game_state.pin_code = data[u'pin']
                self.update_id_label()
                for player in self.game_state.players.players:
                    self.send_player(player)
                self.game_state.players = Players([])
                self.join_btn.text = _('Update')
            except urllib2.HTTPError:
                open_ok_popup(_('Error'), _('Network error'), self)
            except urllib2.URLError:
                open_ok_popup(_('Error'), _('Network error'), self)
        self.update()

    def update_id_label(self):
        self.type_label.text = _("Id: {}, Pin: {}")\
            .format(self.game_state.remote_id, self.game_state.pin_code)

    def load_players(self):
        try:
            loader = JsonLoader()
            data = loader.\
                load_from_url('{}/get_joined_players?game_id={}&pin={}'
                              .format(HOST, self.game_state.remote_id,
                                      self.game_state.pin_code))
            for player in data[u'players']:
                self.game_state.players.add(gamestate.Player(player, []))
            for word in data[u'hat']:
                self.game_state.players.players[word[u'owner']].words.append(
                    (Word(self.game_state.players.players[word[u'owner']],
                          word[u'text'])))
        except urllib2.HTTPError:
            open_ok_popup(_('Error'), _('Network error'), self)
        except urllib2.URLError:
            open_ok_popup(_('Error'), _('Network error'), self)

    def send_player(self, player):
        player_json = {
            u'name': player.name,
            u'words': [],
            u'id': self.game_state.remote_id,
            u'pin': self.game_state.pin_code
        }
        for word in player.words:
            player_json[u'words'].append(word.text)
        loader = JsonLoader()
        try:
            loader.dump_to_url('{}/add_player_from_json'.format(HOST),
                               player_json)
        except urllib2.HTTPError as e:
            if e.code == 409:
                open_ok_popup(_('User name already used'),
                              _('Please use another name'), self)
